﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using caedisi.Web.DataModel;
using caedisi.Models;
using caedisi.Helpers;
using System.Windows.Data;

namespace caedisi.Views.Controls
{
    /// <summary>
    /// The control of the Transition Rule
    /// </summary>
    public partial class TransitionRuleControl : UserControl
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TransitionRuleControl"/> class.
        /// </summary>
        public TransitionRuleControl()
        {
            InitializeComponent();            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TransitionRuleControl"/> class.
        /// </summary>
        /// <param name="transitionRule">The transition rule.</param>
        public TransitionRuleControl(TransitionRule transitionRule)
        {
            InitializeComponent();
            this.CurrentTransitionRule = transitionRule;
        }

        /// <summary>
        /// Gets or sets the current transition rule.
        /// </summary>
        /// <value>
        /// The current transition rule.
        /// </value>
        public TransitionRule CurrentTransitionRule
        {
            get { return (TransitionRule) GetValue(CurrentTransitionRuleProperty); }
            set
            {
                SetValue(CurrentTransitionRuleProperty, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty CurrentTransitionRuleProperty =
                DependencyProperty.Register(
                "CurrentTransitionRule",
                typeof(TransitionRule), 
                typeof(TransitionRuleControl), 
                new PropertyMetadata(OnCurrentEntityChanged));


        /// <summary>
        /// Called when [current entity changed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private static void OnCurrentEntityChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            TransitionRule transitionRule = args.NewValue as TransitionRule;
             
            int minOffset = transitionRule.CellularAutomata.RadiusVisibility * (-1);
            int maxOffset = transitionRule.CellularAutomata.RadiusVisibility * (1);
            int sizeNeighbouringStateConfigurationGrid = maxOffset - minOffset + 1;
            int xIndexCenterCell = maxOffset;
            int yIndexCenterCell = maxOffset;
            int zIndexCenterCell = 0;  //for now we only deal with 2D

            //1. build the grid UI based on the transitionRule data
            TransitionRuleControl transitionRuleControl = sender as TransitionRuleControl;
            //1.a build the dynamic grid of neighbourhood by allocating the number of cells needed in the grid.
            for (int i = 1; i <= sizeNeighbouringStateConfigurationGrid; i++)
            {
                RowDefinition rowDefinition = new RowDefinition();
                rowDefinition.Height = Globals.TransitionRuleControl_GridTransitionRules_RowHeight;
                transitionRuleControl.NeighbouringStateConfigurationGrid.RowDefinitions.Add(rowDefinition);
            }

            for (int i = 1; i <= sizeNeighbouringStateConfigurationGrid; i++)
            {
                ColumnDefinition columnDefinition = new ColumnDefinition();
                columnDefinition.Width = Globals.TransitionRuleControl_GridTransitionRules_ColumnWidth;
                transitionRuleControl.NeighbouringStateConfigurationGrid.ColumnDefinitions.Add(columnDefinition);
            }     
      
            //2. Generate the center cell.
            UIHelper.GenerateBasicCellControl(transitionRuleControl.NeighbouringStateConfigurationGrid, xIndexCenterCell, yIndexCenterCell, zIndexCenterCell, transitionRule, "CurrentCellStateTypeId");    
                        
            //3.  Generate  the neighbouring cells according to the neighbourhoodtype
             foreach (NeighbourhoodStateConfiguration neighourhoodStateConfiguration in transitionRule.NeighbourhoodStateConfigurations)
             {
                 UIHelper.GenerateBasicCellControl(transitionRuleControl.NeighbouringStateConfigurationGrid, 
                     xIndexCenterCell + neighourhoodStateConfiguration.x_offset,
                     yIndexCenterCell + neighourhoodStateConfiguration.y_offset,
                     zIndexCenterCell + neighourhoodStateConfiguration.z_offset
                     , neighourhoodStateConfiguration,
                     "CellStateTypeId");
             }                                  
        }

        ///// <summary>
        ///// Generates the list neighbours data.
        ///// </summary>
        ///// <param name="newTransitionRule">The new transition rule.</param>
        ///// <param name="xIndexCenterCell">The x index center cell.</param>
        ///// <param name="yIndexCenterCell">The y index center cell.</param>
        ///// <param name="zIndexCenterCell">The z index center cell.</param>
        ///// <param name="neighbourhoodType">Type of the neighbourhood.</param>
        ///// <param name="currentRadiusIndex">Index of the current radius.</param>
        //private static void GenerateListNeighboursData(TransitionRule newTransitionRule, int xIndexCenterCell, int yIndexCenterCell, int zIndexCenterCell, NeighbourhoodType neighbourhoodType, int currentRadiusIndex)
        //{
        //    currentRadiusIndex++;
        //    if (currentRadiusIndex > newTransitionRule.CellularAutomata.RadiusVisibility)   //the recursion ends when the distance thresold  has ben met
        //        return;

        //    if (neighbourhoodType.IsTopLeftON)
        //    {
        //        int xIndex = xIndexCenterCell - 1;
        //        int yIndex = yIndexCenterCell - 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsTopON)
        //    {
        //        int xIndex = xIndexCenterCell - 1;
        //        int yIndex = yIndexCenterCell;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsTopRightON)
        //    {
        //        int xIndex = xIndexCenterCell - 1;
        //        int yIndex = yIndexCenterCell + 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsRightON)
        //    {
        //        int xIndex = xIndexCenterCell;
        //        int yIndex = yIndexCenterCell + 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsBottomRightON)
        //    {
        //        int xIndex = xIndexCenterCell + 1;
        //        int yIndex = yIndexCenterCell + 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsBottomON)
        //    {
        //        int xIndex = xIndexCenterCell + 1;
        //        int yIndex = yIndexCenterCell;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsBottomLeftON)
        //    {
        //        int xIndex = xIndexCenterCell + 1;
        //        int yIndex = yIndexCenterCell - 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }

        //    if (neighbourhoodType.IsLeftON)
        //    {
        //        int xIndex = xIndexCenterCell;
        //        int yIndex = yIndexCenterCell - 1;
        //        int zIndex = 0;

        //        GenerateDirectNeighbourData(newTransitionRule, xIndex, yIndex, zIndex);
        //        GenerateListNeighboursData(newTransitionRule, xIndex, yIndex, zIndex, neighbourhoodType, currentRadiusIndex);
        //    }
        //}


        ///// <summary>
        ///// Generates the direct neighbour data.
        ///// </summary>
        ///// <param name="transitionRule">The transition rule.</param>
        ///// <param name="xIndex">Index of the x.</param>
        ///// <param name="yIndex">Index of the y.</param>
        ///// <param name="zIndex">Index of the z.</param>
        //private static void GenerateDirectNeighbourData(TransitionRule transitionRule, int xIndex, int yIndex, int zIndex)
        //{
        //    int x_offset = xIndex - transitionRule.CellularAutomata.RadiusVisibility;
        //    int y_offset = yIndex - transitionRule.CellularAutomata.RadiusVisibility;
        //    int z_offset = 0;

        //    bool isGridCellEmpty = transitionRule.NeighbourhoodStateConfigurations.Where( neighbourhoodStateConfiguration => neighbourhoodStateConfiguration.x_offset == x_offset
        //                                                                                                                && neighbourhoodStateConfiguration.y_offset == y_offset
        //                                                                                                                && neighbourhoodStateConfiguration.z_offset == z_offset).Count() == 0;
        //    if (isGridCellEmpty)
        //    {
        //        NeighbourhoodStateConfiguration newNeighbourState = new NeighbourhoodStateConfiguration()
        //        {
        //            x_offset = x_offset,
        //            y_offset = x_offset,
        //            z_offset = z_offset,
        //        };                
        //    }
        //}
    }
}
